import datetime
import html
import uuid

from apscheduler.schedulers.background import BackgroundScheduler
from django.conf import settings
from django_apscheduler.jobstores import DjangoJobStore
from rest_framework.response import Response
from book.models import Book
from book.serializers import BookSerializer
from django.core.paginator import Paginator, Page
# Create your views here.
from rest_framework.views import APIView

from common import CommonResult
from equipments.models import Equipment
from utils.MyPageNumberPagination import QueryWrapper, MyPageNumberPagination
from users.models import User
from django.db import transaction
# book = Book.objects.all()
# print(book)
# ser = BookSerializer(instance=book, many=True)
# print(ser.data)

# 实例化调度器
from users.schedule import send_notify_email, auto_release_equipment

scheduler = BackgroundScheduler(timezone=settings.TIME_ZONE)
# 调度器使用DjangoJobStore()
scheduler.add_jobstore(DjangoJobStore(), "default")
scheduler.start()


# 设置定时发送邮件任务，通知用户订单即将结束，传入计时任务scheduler、字典book_data,字典中包含设备预计过期时间和用户id
def schedule_work(scheduler, book_data):
    fmt = '%Y-%m-%d %H:%M:%S'
    booker_email = book_data['u_id']
    expire_date_str = book_data['expire_date']
    # 判断expire_date_str是字符串类型还是datetime类型
    expire_date = datetime.datetime.strptime(expire_date_str, fmt)
    notify_date = expire_date - datetime.timedelta(days=1)
    notify_date_str = notify_date.strftime(fmt)
    if notify_date > datetime.datetime.now():
        scheduler.add_job(
            send_notify_email,
            'date',
            run_date=notify_date_str,
            id="notify_email_" + book_data['b_id'],
            max_instances=1,
            replace_existing=True,
            args=[booker_email]
        )
    if expire_date > datetime.datetime.now():
        scheduler.add_job(
            auto_release_equipment,
            'date',
            run_date=expire_date_str,
            id='release_equipment_' + book_data['b_id'],
            max_instances=1,
            replace_existing=True,
            args=[book_data['b_id'], book_data['e_id'], book_data['u_id']]
        )


# 移除定时任务，针对用户主动释放设备或者续订设备，删除原先的定时发送邮件任务；
def schedule_remove(scheduler, b_id):
    notify_id = "notify_email_" + b_id
    release_id = "release_equipment_" + b_id
    # 删除定时发送邮件任务
    try:
        scheduler.remove_job(notify_id)
    except Exception as e:
        print(e)
    # 删除定时结束订单任务
    try:
        scheduler.remove_job(release_id)
    except Exception as e:
        print(e)


# 1.获取单个用户历史订单，get请求，拼接上u_id;按照结束时间倒序返回
class HistoryBook(APIView):
    def get(self, request):
        sql = "SELECT a.b_id,a.subscribe_date,a.expire_date,a.end_time,a.extend,b.* FROM hwb_book a , hwb_equipment b WHERE a.e_id = b.e_id AND a.u_id ='%s' AND a.b_status = false order by end_time desc " % (
            html.unescape(request.query_params.get('u_id')))
        queryset = QueryWrapper(sql)
        page = MyPageNumberPagination()
        page_roles = page.paginate_queryset(queryset=queryset, request=request)[:3]
        return page.get_paginated_response(page_roles)


# 2.查询用户目前在进行的订单，get请求，拼接上u_id;按照预期时间顺序返回
class NowBook(APIView):
    def get(self, request):
        sql = "SELECT a.b_id,a.subscribe_date,a.expire_date,a.end_time,a.extend,b.* FROM hwb_book a , hwb_equipment b WHERE a.e_id = b.e_id AND a.u_id ='%s' AND a.b_status = true " % (
            html.unescape(request.query_params.get('u_id')))
        queryset = QueryWrapper(sql)
        page = MyPageNumberPagination()
        page_roles = page.paginate_queryset(queryset=queryset, request=request)
        return page.get_paginated_response(page_roles)


# 3.订单续订，get请求，拼接上用户id。每次续订时间为3天，用户最多可以将一个订单续订三天；删除原先定时发送邮件任务，新添邮件发送任务；
class ExtendBook(APIView):
    def get(self, request):
        b_id = request.query_params.get('b_id')
        days = 3
        book = Book.objects.get(b_id=b_id)
        book_data = {"b_id": b_id, 'e_id': book.e_id}
        # 获取用户信息
        u_id = book.u_id
        user = User.objects.get(id=u_id)
        if user.is_staff == 0 and book.extend == 3:
            return CommonResult.ok("对不起，您的续订机会已经用完")
        else:
            # 管理员续订
            if request.query_params.get('expire_date') is not None:
                book.extend = 999
                book_data['expire_date'] = request.query_params.get('expire_date')
                book.expire_date = request.query_params.get('expire_date')
                book_data['u_id'] = book.u_id
                schedule_work(scheduler, book_data)
                book.save()
                return CommonResult.ok('续订成功')
            # 非管理员续订
            else:
                book.extend = book.extend + 1
                book.expire_date = book.expire_date + datetime.timedelta(days=days)
                book.expire_date = book.expire_date.strftime('%Y-%m-%d %H:%M:%S')
                book_data["expire_date"] = book.expire_date
                book_data['u_id'] = book.u_id
                schedule_work(scheduler, book_data)
                book.save()
                return CommonResult.ok('续订成功')


# 4.订单续订，get请求，拼接上用户id。每次续订时间为3天，用户最多可以将一个订单续订三天；删除原先定时发送邮件任务，新添邮件发送任务；
class BookEquipment(APIView):
    @transaction.atomic
    def post(self, request):
        # 获取book表订阅数据
        book_data = request.data.copy()
        equipment = Equipment.objects.get(e_id=book_data['e_id'])
        if equipment.e_status == 1:
            return CommonResult.params_error("设备已被预订")
        book_data['b_id'] = uuid.uuid1().hex
        serializer = BookSerializer(data=book_data, partial=True)
        equipment.e_status = 1
        equipment.save()
        if serializer.is_valid(raise_exception=True):
            serializer.save()
            # 添加定时任务
            schedule_work(scheduler, book_data)
            return CommonResult.ok('订阅成功')
        else:
            return CommonResult.params_error('参数错误')


# 5.结束订单，Get请求，传入订单id，结束订单，释放设备，移除定时发送邮件任务；
class EndBook(APIView):
    def get(self, request):
        id = request.query_params.get('b_id')
        book = Book.objects.get(b_id=id)
        e_id = book.e_id
        if book.b_status == False:
            return CommonResult.ok("该订单是历史订单")
        else:
            book.end_time = datetime.datetime.now()
            book.b_status = False
            book.save()
            # 去除定时任务
            schedule_remove(scheduler, id)
            # 释放订单设备
            equipment = Equipment.objects.get(e_id=e_id)
            equipment.e_status = 0
            equipment.save()
            return CommonResult.ok("结束订单成功")


# 6.查询所有订单，并且包括订单拥有者
class AllBook(APIView):
    def get(self, request):
        sql = "select hwb_book.*,username from hwb_book,hwb_users where hwb_book.u_id = hwb_users.username and b_status = true"
        queryset = QueryWrapper(sql)
        page = MyPageNumberPagination()
        page_role = page.paginate_queryset(queryset=queryset, request=request)
        return page.get_paginated_response(page_role)


# 7.查询最近10天的设备使用量，get请求，传入用户id，返回最近10天所有用户每天的订单数量、该用户的每天订单数量、前10天每天日期；
class BookStaticView(APIView):
    def get(self, request):
        username = request.query_params.get('username')
        now_date = datetime.date.today()
        date_list = []
        total_usage = []
        user_uage = []
        for i in range(10, 0, -1):
            start = now_date - datetime.timedelta(days=i)
            end = now_date - datetime.timedelta(days=i - 1)
            books_total = Book.objects.filter(b_status=True).filter(subscribe_date__gte=start).filter(
                subscribe_date__lt=end)
            books_user = Book.objects.filter(b_status=True).filter(subscribe_date__gte=start).filter(
                subscribe_date__lt=end).filter(u_id=username)
            date_list.append(start.strftime('%m-%d'))
            total_usage.append(len(books_total))
            user_uage.append(len(books_user))
        result = {
            'data_list': date_list,
            'total_usage': total_usage,
            'user_usage': user_uage
        }
        return CommonResult.ok('统计数据', result)
